<template>
  <div class="video-management">
    <div class="page-header">
      <h1>视频管理</h1>
      <a-button type="primary" @click="showAddModal = true">
        <template #icon>
          <PlusOutlined />
        </template>
        添加视频
      </a-button>
    </div>

    <!-- 搜索和筛选 -->
    <div class="search-section">
      <a-row :gutter="16">
        <a-col :span="6">
          <a-input-search v-model:value="searchKeyword" placeholder="搜索视频名称" @search="handleSearch" />
        </a-col>
        <a-col :span="4">
          <a-button @click="resetFilters">重置筛选</a-button>
        </a-col>
      </a-row>
    </div>

    <!-- 视频列表 -->
    <div class="video-table">
      <a-table :columns="columns" :data-source="filteredVideos" :pagination="pagination" :loading="loading"
               row-key="id">
        <template #bodyCell="{ column, record }">
          <template v-if="column.key === 'thumbnail'">
            <img :src="record.thumbnail" :alt="record.title" class="video-thumbnail" />
          </template>
          <template v-else-if="column.key === 'action'">
            <a-space>
              <a-button type="link" @click="previewVideo(record)">预览</a-button>
              <a-popconfirm title="确定要删除这个视频吗？" @confirm="deleteVideo(record.id)">
                <a-button type="link" danger>删除</a-button>
              </a-popconfirm>
            </a-space>
          </template>
        </template>
      </a-table>
    </div>

    <!-- 添加/编辑视频弹窗 -->
    <a-modal v-model:open="showAddModal" :title="isEditing ? '编辑视频' : '添加视频'" width="800px"
             @cancel="handleCancel">
      <a-form ref="formRef" :model="videoForm"  layout="vertical">
        <a-form-item label="视频文件" name="videoUrl">
          <a-upload-dragger v-model:file-list="videoFileList" :multiple="false" :before-upload="beforeVideoUpload"
                            :show-upload-list="true">
            <p class="ant-upload-drag-icon">
              <VideoCameraOutlined />
            </p>
            <p class="ant-upload-text">点击或拖拽视频文件到此处上传</p>
            <p class="ant-upload-hint">
              支持MP4、MOV等常见视频格式，文件大小不超过2GB
            </p>
          </a-upload-dragger>
          <a-progress v-if="isUploading" :percent="uploadProgress" style="margin-top: 16px;" />
        </a-form-item>
        <a-form-item label="备注" name="remark">
          <a-input v-model:value="videoForm.remark" placeholder="请输入备注信息" />
        </a-form-item>
      </a-form>
    </a-modal>

    <!-- 视频预览弹窗 -->
    <a-modal v-model:open="showPreviewModal" title="视频预览" width="70%" :footer="null" @cancel="closePreview">
      <div class="video-preview-container">
        <video controls autoplay :src="previewVideoUrl" style="width: 100%;"></video>
        <div class="video-info">
          <h3>{{ previewVideoTitle }}</h3>
          <p>{{ previewVideoDescription }}</p>
        </div>
      </div>
    </a-modal>
  </div>
</template>

<script setup lang="ts">
import { reactive, computed, ref, onMounted, watch } from 'vue'
import { PlusOutlined, VideoCameraOutlined } from '@ant-design/icons-vue'
import type { FormInstance } from 'ant-design-vue'
import { message } from 'ant-design-vue';
import { checkFile, checkChunk, uploadChunk, mergeChunks, getMediaFileList, deleteVideoById } from '@/api/bizMediaFileController.ts';
import SparkMD5 from 'spark-md5';
// 直接在本地定义类型，避免 d.ts 导入报错
// import type { BizMediaFile, getMediaFileListParams } from '@/api/typings';
// import { log } from 'echarts/types/src/util/log.js';

type BizMediaFile = {
  id?: number;
  fileName?: string;
  fileType?: number;
  createTime?: string;
  remark?: string;
  filePath?: string;
  duration?: number;
  status?: number;
  quality?: string;
};
type getMediaFileListParams = {
  videoPageListVo: {
    current: number;
    pageSize: number;
    fileName?: string;
  }
};

// 响应式数据
const loading = ref(false)
const searchKeyword = ref('')
const showAddModal = ref(false)
const showPreviewModal = ref(false)
const isEditing = ref(false)
const videoFileList = ref([])
const formRef = ref<FormInstance>();
const previewVideoUrl = ref('')
const previewVideoTitle = ref('')
const previewVideoDescription = ref('')
const videoList = ref<BizMediaFile[]>([]);
const total = ref(0);

// 视频表单
const videoForm = reactive({
  id: null,
  fileName: '',
  remark: '',
  fileType: 1
})

// 分页配置
const pagination = reactive({
  current: 1,
  pageSize: 10,
  total: 0,
  showSizeChanger: true,
  showQuickJumper: true,
  showTotal: (total: number) => `共 ${total} 条记录`,
  pageSizeOptions: ['10', '20', '50', '100'],
  showLessItems: true,
  locale: {
    items_per_page: '条/页',
    jump_to: '跳至',
    jump_to_confirm: '确定',
    page: '页',
    prev_page: '上一页',
    next_page: '下一页',
    prev_5: '向前 5 页',
    next_5: '向后 5 页',
    prev_3: '向前 3 页',
    next_3: '向后 3 页',
  }
})

// 表格列配置
const columns = [
  {
    title: '文件名称',
    dataIndex: 'fileName',
    key: 'fileName',
    width: 200,
    align: 'center'
  },
  {
    title: '文件类型',
    dataIndex: 'fileType',
    key: 'fileType',
    width: 100,
    align: 'center',
    customRender: ({ text }: { text: string | number }) => {
      const fileTypeMap: Record<string, string> = { '1': '视频', '2': '文档', '3': '图片' };
      return fileTypeMap[String(text)] || '未知';
    }
  },
  {
    title: '上传时间',
    dataIndex: 'createTime',
    key: 'createTime',
    width: 200,
    align: 'center'
  },
  {
    title: '备注',
    dataIndex: 'remark',
    key: 'remark',
    width: 200,
    align: 'center'
  },
  {
    title: '操作',
    key: 'action',
    width: 200,
    fixed: 'right',
    align: 'center'
  }
]

// 在组件中添加以下响应式数据
const uploadProgress = ref(0);
const isUploading = ref(false);
const chunkSize = 5 * 1024 * 1024; // 5MB

// 加载视频列表
const loadVideoList = async () => {
  loading.value = true;
  try {
    const params: getMediaFileListParams = {
      videoPageListVo: {
        current: pagination.current,
        pageSize: pagination.pageSize,
        fileName: searchKeyword.value
      }
    };
    const response = await getMediaFileList(params);
    console.log(response);
    
    if (response.data.data) {
      videoList.value = response.data.data.list || [];
      total.value = response.data.data.total || 0;
      pagination.total = total.value;
    }
  } catch (error) {
    console.error('加载视频列表失败:', error);
    message.error('加载视频列表失败');
  } finally {
    loading.value = false;
  }
};

// 页面挂载时加载数据
onMounted(() => {
  loadVideoList();
});

// 监听分页变化
watch([() => pagination.current, () => pagination.pageSize], () => {
  loadVideoList();
});

// 修改 beforeVideoUpload 方法
const beforeVideoUpload = async (file: File) => {
  try {
    isUploading.value = true;
    uploadProgress.value = 0;

    // 1. 计算文件MD5（唯一标识）
    const fileMd5 = await calculateFileMD5(file);

    // 2. 检查整个文件是否已存在
    const { data: fileExists } = await checkFile({ fileMd5 });
    console.log(fileExists);
    if (fileExists.data) {
      message.success('文件已存在，无需重复上传');
      isUploading.value = false;
      return false;
    }

    // 3. 计算分块数量
    const chunkTotal = Math.ceil(file.size / chunkSize);

    // 4. 上传所有分块
    await uploadAllChunks(file, fileMd5, chunkTotal);

    // 5. 合并分块
    await mergeChunks({ fileMd5, fileName: file.name, chunkTotal });

    message.success('视频上传成功');
    showAddModal.value = false;
    loadVideoList(); // 上传成功后重新加载列表
    return false; // 阻止默认上传行为
  } catch (error) {
    console.error('上传失败:', error);
    message.error('视频上传失败');
    return false;
  } finally {
    isUploading.value = false;
  }
};

// 计算文件MD5
const calculateFileMD5 = (file: File): Promise<string> => {
  return new Promise((resolve, reject) => {
    const blobSlice = File.prototype.slice;
    const chunkSize = 2 * 1024 * 1024; // 2MB chunks
    const chunks = Math.ceil(file.size / chunkSize);
    let currentChunk = 0;
    const spark = new SparkMD5.ArrayBuffer();
    const fileReader = new FileReader();

    fileReader.onload = function(e) {
      spark.append(e.target?.result as ArrayBuffer);
      currentChunk++;

      if (currentChunk < chunks) {
        loadNext();
      } else {
        resolve(spark.end());
      }
    };

    fileReader.onerror = function() {
      reject(new Error('文件读取失败'));
    };

    function loadNext() {
      const start = currentChunk * chunkSize;
      const end = ((start + chunkSize) >= file.size) ? file.size : start + chunkSize;
      fileReader.readAsArrayBuffer(blobSlice.call(file, start, end));
    }

    loadNext();
  });
};

// 上传所有分块
const uploadAllChunks = async (file: File, fileMd5: string, chunkTotal: number) => {
  const chunksToUpload: number[] = [];

  // 检查哪些分块需要上传
  for (let chunk = 0; chunk < chunkTotal; chunk++) {
    const { data: chunkExists } = await checkChunk({ fileMd5, chunk });
    if (!chunkExists.data) {
      chunksToUpload.push(chunk);
    }
  }

  // 如果没有需要上传的分块，直接返回
  if (chunksToUpload.length === 0) {
    return;
  }

  // 上传需要上传的分块
  for (const chunk of chunksToUpload) {
    const start = chunk * chunkSize;
    const end = Math.min(file.size, start + chunkSize);
    const chunkBlob = file.slice(start, end);

    const formData = new FormData();
    formData.append('file', chunkBlob);  // 只传文件

    await uploadChunk(
      { fileMd5, chunk },  // MD5和分块号通过URL参数传递
      formData,
      {
        headers: {
          'Content-Type': 'multipart/form-data',
        },
      }
    );

    uploadProgress.value = Math.floor(((chunk + 1) / chunkTotal) * 100);
  }
};

// 计算属性
const filteredVideos = computed(() => videoList.value)

// 方法
const handleSearch = () => {
  pagination.current = 1;
  loadVideoList();
}

const resetFilters = () => {
  searchKeyword.value = '';
  pagination.current = 1;
  loadVideoList();
}

const editVideo = (video: BizMediaFile) => {
  isEditing.value = true;
  Object.assign(videoForm, video);
  showAddModal.value = true;
}

const VIDEO_BASE_URL = import.meta.env.VITE_VIDEO_BASE_URL as string;
console.log(VIDEO_BASE_URL);


const previewVideo = (video: BizMediaFile) => {
  previewVideoUrl.value = VIDEO_BASE_URL + video.filePath;
  previewVideoTitle.value = video.fileName || '';
  previewVideoDescription.value = video.remark || '';
  showPreviewModal.value = true;
}

const closePreview = () => {
  showPreviewModal.value = false;
  previewVideoUrl.value = '';
}

const deleteVideo = async (id: number) => {
  try {
    const response = await deleteVideoById({ id });
    if (response.data) {
      message.success('删除成功');
      loadVideoList();
    } else {
      message.error('删除失败');
    }
  } catch (error) {
    console.error('删除视频失败:', error);
    message.error('删除视频失败');
  }
}

const handleCancel = () => {
  showAddModal.value = false;
  resetForm();
}

const resetForm = () => {
  Object.assign(videoForm, {
    id: null,
    fileName: '',
    remark: '',
    fileType: 1
  });
  isEditing.value = false;
  videoFileList.value = [];
}
</script>


<style scoped>
.video-management {
  padding: 0;
}

.page-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 24px;
}

.page-header h1 {
  margin: 0;
  color: #333;
}

.search-section {
  background: #f5f5f5;
  padding: 16px;
  border-radius: 8px;
  margin-bottom: 16px;
}

.video-table {
  background: #fff;
  border-radius: 8px;
}

.video-thumbnail {
  width: 80px;
  height: 60px;
  object-fit: cover;
  border-radius: 4px;
}

.ant-upload-select-picture-card {
  width: 120px;
  height: 90px;
}

.ant-upload-select-picture-card img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.video-preview-container {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.video-info {
  padding: 16px;
  background: #f5f5f5;
  border-radius: 4px;
}

.video-info h3 {
  margin: 0 0 8px 0;
  font-size: 18px;
}

.video-info p {
  margin: 0;
  color: #666;
}
</style>
